package cn.chengpengper.seckill.order.application.place;


import cn.chengpengper.seckill.common.code.HttpCode;
import cn.chengpengper.seckill.common.constants.SeckillConstants;
import cn.chengpengper.seckill.common.exception.SeckillException;
import cn.chengpengper.seckill.common.model.message.TxMessage;
import cn.chengpengper.seckill.common.model.dto.SeckillGoodsDTO;
import cn.chengpengper.seckill.common.model.enums.SeckillGoodsStatus;
import cn.chengpengper.seckill.common.model.enums.SeckillOrderStatus;
import cn.chengpengper.seckill.common.utils.bean.BeanUtil;
import cn.chengpengper.seckill.common.utils.id.SnowFlakeFactory;
import cn.chengpengper.seckill.order.application.model.command.SeckillOrderCommand;
import cn.chengpengper.seckill.order.domain.model.entity.SeckillOrder;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;
import com.alibaba.fastjson.JSONObject;

import java.math.BigDecimal;
import java.util.Date;
import java.util.Objects;

/**
 * 下单服务
 *
 * @author chengpeng.hu
 */
public interface SeckillPlaceOrderService {

    /**
     * 下单
     *
     * @param userId              用户ID
     * @param seckillOrderCommand 订单命令
     * @return
     */
    Long placeOrder(Long userId, SeckillOrderCommand seckillOrderCommand);

    /**
     * 本地事务执行保存订单操作
     */
    void saveOrderInTransaction(TxMessage txMessage);

    /**
     * 构建订单
     *
     * @param userId              用户ID
     * @param seckillOrderCommand 订单命令
     * @param seckillGoods        商品
     * @return 订单
     */
    default SeckillOrder buildSeckillOrder(Long userId, SeckillOrderCommand seckillOrderCommand, SeckillGoodsDTO seckillGoods) {
        SeckillOrder seckillOrder = new SeckillOrder();
        BeanUtil.copyProperties(seckillOrderCommand, seckillOrder);
        seckillOrder.setId(SnowFlakeFactory.getSnowFlakeFromCache().nextId());
        seckillOrder.setGoodsName(seckillGoods.getGoodsName());
        seckillOrder.setUserId(userId);
        seckillOrder.setActivityPrice(seckillGoods.getActivityPrice());
        BigDecimal orderPrice = seckillOrder.getActivityPrice().multiply(BigDecimal.valueOf(seckillOrderCommand.getQuantity()));
        seckillOrder.setOrderPrice(orderPrice);
        seckillOrder.setStatus(SeckillOrderStatus.CREATED.getCode());
        seckillOrder.setCreateTime(new Date());
        return seckillOrder;
    }

    /**
     * 构建订单
     */
    default SeckillOrder buildSeckillOrder(TxMessage txMessage){
        SeckillOrder seckillOrder = new SeckillOrder();
        seckillOrder.setId(txMessage.getTxNo());
        seckillOrder.setUserId(txMessage.getUserId());
        seckillOrder.setGoodsId(txMessage.getGoodsId());
        seckillOrder.setGoodsName(txMessage.getGoodsName());
        seckillOrder.setActivityPrice(txMessage.getActivityPrice());
        seckillOrder.setQuantity(txMessage.getQuantity());
        BigDecimal orderPrice = txMessage.getActivityPrice().multiply(BigDecimal.valueOf(seckillOrder.getQuantity()));
        seckillOrder.setOrderPrice(orderPrice);
        seckillOrder.setActivityId(txMessage.getActivityId());
        seckillOrder.setStatus(SeckillOrderStatus.CREATED.getCode());
        seckillOrder.setCreateTime(new Date());
        return seckillOrder;
    }


    /**
     * 下单预校验
     *
     * @param seckillOrderCommand 订单命令
     * @param seckillGoods        商品信息
     */
    default void checkSeckillOrder(SeckillOrderCommand seckillOrderCommand, SeckillGoodsDTO seckillGoods) {
        // 1、商品不存在
        if (Objects.isNull(seckillGoods)) {
            throw new SeckillException(HttpCode.GOODS_NOT_EXISTS);
        }
        // 2、商品未上线
        if (SeckillGoodsStatus.PUBLISHED.getCode().equals(seckillGoods.getStatus())) {
            throw new SeckillException(HttpCode.GOODS_PUBLISH);
        }
        // 3、商品已下线
        if (SeckillGoodsStatus.OFFLINE.getCode().equals(seckillGoods.getStatus())) {
            throw new SeckillException(HttpCode.GOODS_OFFLINE);
        }
        // 4、触发限购
        if (seckillGoods.getLimitNum() < seckillOrderCommand.getQuantity()) {
            throw new SeckillException(HttpCode.BEYOND_LIMIT_NUM);
        }
        // 5、库存不足
        if (Objects.isNull(seckillGoods.getAvailableStock()) || seckillGoods.getAvailableStock() <= 0 || seckillGoods.getAvailableStock() < seckillOrderCommand.getQuantity()) {
            throw new SeckillException(HttpCode.STOCK_LT_ZERO);
        }
    }

    /**
     * 事务消息
     */
    default TxMessage getTxMessage(String destination, Long txNo, Long userId, String placeOrderType, Boolean exception,
                                   SeckillOrderCommand seckillOrderCommand, SeckillGoodsDTO seckillGoods, Integer bucketSerialNo, String orderTaskId){
        //构建事务消息
        return new TxMessage(destination, txNo, seckillOrderCommand.getGoodsId(), seckillOrderCommand.getQuantity(),
                seckillOrderCommand.getActivityId(), seckillOrderCommand.getVersion(), userId, seckillGoods.getGoodsName(),
                seckillGoods.getActivityPrice(), placeOrderType, exception, bucketSerialNo,orderTaskId);
    }

}
